package me.zhengjie.modules.property.service;

import me.zhengjie.modules.property.domain.Payment;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;

public class LoanCalculator {

    public static List<Payment> calculateEqualPrincipalAndInterest(BigDecimal loanAmount, BigDecimal annualInterestRate, int loanTermMonths) {
        List<Payment> payments = new ArrayList<>();

        BigDecimal monthlyInterestRate = annualInterestRate.divide(BigDecimal.valueOf(12), 6, RoundingMode.HALF_UP);
        BigDecimal monthlyPayment = loanAmount.multiply(monthlyInterestRate).divide(BigDecimal.ONE.subtract(
                BigDecimal.ONE.divide(BigDecimal.ONE.add(monthlyInterestRate).pow(loanTermMonths), 6, RoundingMode.HALF_UP))
        , 2, RoundingMode.HALF_UP);

        for (int i = 0; i < loanTermMonths; i++) {
            BigDecimal interestPayment = loanAmount.multiply(monthlyInterestRate);
            BigDecimal principalPayment = monthlyPayment.subtract(interestPayment);

            Payment payment = new Payment(i + 1, monthlyPayment, principalPayment, interestPayment);
            payments.add(payment);

            loanAmount = loanAmount.subtract(principalPayment);
        }
        return payments;
    }

    public static List<Payment> calculateEqualPrincipal(BigDecimal loanAmount, BigDecimal annualInterestRate, int loanTermMonths) {
        List<Payment> payments = new ArrayList<>();

        BigDecimal monthlyInterestRate = annualInterestRate.divide(BigDecimal.valueOf(12), 6, RoundingMode.HALF_UP);
        BigDecimal principalPayment = loanAmount.divide(BigDecimal.valueOf(loanTermMonths), 2, RoundingMode.HALF_UP);

        for (int i = 0; i < loanTermMonths; i++) {
            BigDecimal interestPayment = loanAmount.multiply(monthlyInterestRate);
            BigDecimal monthlyPayment = principalPayment.add(interestPayment);

            Payment payment = new Payment(i + 1, monthlyPayment, principalPayment, interestPayment);
            payments.add(payment);

            loanAmount = loanAmount.subtract(principalPayment);
        }

        return payments;
    }

    // 计算等额本息还款总额
    public static double calculateRepaymentAmountEqualInstallment(double interestRate, double loanAmount, int loanTermYears) {
        double monthlyInterestRate = interestRate / 12; // 月利率
        int loanTermMonths = loanTermYears; // 总月数

        double monthlyPayment = loanAmount * monthlyInterestRate * Math.pow(1 + monthlyInterestRate, loanTermMonths)
                / (Math.pow(1 + monthlyInterestRate, loanTermMonths) - 1);

        double repaymentAmount = monthlyPayment * loanTermMonths;

        return repaymentAmount;
    }

    // 计算等额本息利息总额
    public static double calculateInterestAmountEqualInstallment(double repaymentAmount, double loanAmount) {
        double interestAmount = repaymentAmount - loanAmount;

        return interestAmount;
    }

    // 计算等额本金还款总额
    public static double calculateRepaymentAmountEqualPrincipal(double interestRate, double loanAmount, int loanTermYears) {
        double monthlyInterestRate = interestRate / 12; // 月利率
        int loanTermMonths = loanTermYears; // 总月数

        double repaymentAmount = loanAmount / loanTermMonths;

        double totalInterestAmount = 0;
        for (int i = 0; i < loanTermMonths; i++) {
            double interestAmount = loanAmount * monthlyInterestRate;
            totalInterestAmount += interestAmount;
            loanAmount -= repaymentAmount;
        }

        repaymentAmount += totalInterestAmount;

        return repaymentAmount;
    }

    // 计算等额本金利息总额
    public static double calculateInterestAmountEqualPrincipal(double repaymentAmount, double loanAmount) {
        double interestAmount = repaymentAmount - loanAmount;

        return interestAmount;
    }

}